package com.simple.common.utils;

import cn.hutool.core.convert.Convert;
import com.google.common.base.Strings;
import com.simple.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.xdb.Searcher;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * @Description 获取IP地址工具类
 * @Author xiaoke
 * @Date 2024/8/10 18:00
 * @Version 1.0
 */
@Slf4j
public class IpUtils {

    private static final Searcher SEARCHER;

    static {
        InputStream in = IpUtils.class.getClassLoader().getResourceAsStream("ip2region.xdb");
        if (in == null) {
            throw new RuntimeException("ip数据加载失败");
        }
        BufferedInputStream bis = new BufferedInputStream(in);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            int len;
            byte[] buffer = new byte[8192];
            while ((len = bis.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
        } catch (IOException e) {
            throw new RuntimeException("ip数据加载失败");
        }
        try {
            SEARCHER = Searcher.newWithBuffer(out.toByteArray());
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("ip数据加载失败");
        }
        try {
            bis.close();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private IpUtils() {

    }

    public static String getIpAddr(HttpServletRequest request) {
        String xIp = request.getHeader("X-Real-IP");
        String xFor = request.getHeader("X-Forwarded-For");

        if (!Strings.isNullOrEmpty(xFor) && !"unKnown".equalsIgnoreCase(xFor)) {
            //多次反向代理后会有多个ip值，第一个ip才是真实ip
            int index = xFor.indexOf(",");
            if (index != -1) {
                return xFor.substring(0, index);
            } else {
                return xFor;
            }
        }
        xFor = xIp;
        if (!Strings.isNullOrEmpty(xFor) && !"unKnown".equalsIgnoreCase(xFor)) {
            return xFor;
        }
        if (Strings.nullToEmpty(xFor).trim().isEmpty() || "unknown".equalsIgnoreCase(xFor)) {
            xFor = request.getHeader("Proxy-Client-IP");
        }
        if (Strings.nullToEmpty(xFor).trim().isEmpty() || "unknown".equalsIgnoreCase(xFor)) {
            xFor = request.getHeader("WL-Proxy-Client-IP");
        }
        if (Strings.nullToEmpty(xFor).trim().isEmpty() || "unknown".equalsIgnoreCase(xFor)) {
            xFor = request.getHeader("HTTP_CLIENT_IP");
        }
        if (Strings.nullToEmpty(xFor).trim().isEmpty() || "unknown".equalsIgnoreCase(xFor)) {
            xFor = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (Strings.nullToEmpty(xFor).trim().isEmpty() || "unknown".equalsIgnoreCase(xFor)) {
            xFor = request.getRemoteAddr();
        }
        return "0:0:0:0:0:0:0:1".equals(xFor) ? "127.0.0.1" : xFor;
    }

    /**
     * 解析ip
     *
     * @param ip ip地址
     * @return ip归属地--索引: 0 省份 1 城市
     */
    public static String[] parseIpAddr(String ip) {
        if (ip.equals("127.0.0.1")) return new String[]{"内网"};
        try {
            String search = SEARCHER.search(Searcher.checkIP(ip));
            if (search != null) {
                String[] split = search.split("\\|");
                System.out.println(Arrays.toString(split));
                boolean fig = split[2].equals("0") && split[3].equals("0");
                return fig ? new String[]{"中国", "中国"} : new String[]{split[2], split[3]};
            } else {
                return new String[]{"未知", "未知"};
            }
        } catch (Exception e) {
            throw new ServiceException("ip解析失败");
        }
    }

    /**
     * 获取WebSocket IP地址
     * @param map map
     * @return IP地址
     */
    public static String getIpAddrByHandshakeRequest(Map<String, List<String>> map) {
        if (map == null) {
            return null;
        }

        String ip = null;

        // X-Forwarded-For：Squid 服务代理
        String ipAddresses = Convert.toStr(map.get("X-Forwarded-For"));
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            // Proxy-Client-IP：apache 服务代理
            ipAddresses = Convert.toStr(map.get("Proxy-Client-IP"));
        } else {
            ipAddresses = ipAddresses.substring(1, ipAddresses.length() - 1);
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            // WL-Proxy-Client-IP：weblogic 服务代理
            ipAddresses = Convert.toStr(map.get("WL-Proxy-Client-IP"));
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            // HTTP_CLIENT_IP：有些代理服务器
            ipAddresses = Convert.toStr(map.get("HTTP_CLIENT_IP"));
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            // X-Real-IP：nginx服务代理
            ipAddresses = Convert.toStr(map.get("X-Real-IP"));
        }

        // 有些网络通过多层代理，那么获取到的ip就会有多个，一般都是通过逗号（,）分割开来，并且第一个ip为客户端的真实IP
        if (ipAddresses != null && ipAddresses.length() != 0) {
            ip = ipAddresses.split(",")[0];
        }
        if(ip == null) {
            return "127.0.0.1";
        }
        return ip.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip;
    }


}
